package com.manolo.event.dispatcher;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import java.util.Iterator;

import com.manolo.event.listener.SystemListener;
import com.manolo.event.PlayerListEvent;
import com.manolo.event.SystemEvent;

public class SystemDispatcher {
	private static SystemDispatcher instance;
	private List<SystemListener> externalListeners;
	private List<SystemListener> localListeners;

	private SystemDispatcher() {
		this.localListeners = new ArrayList<SystemListener>();
		this.externalListeners = new ArrayList<SystemListener>();
	}

	public synchronized static SystemDispatcher getInstance() {
		if(SystemDispatcher.instance == null) {
			SystemDispatcher.instance = new SystemDispatcher();
		}

		return SystemDispatcher.instance;
	}

	public void addLocalListener(SystemListener listener) {
		this.localListeners.add(listener);
	}
	
	public void addExternalListener(SystemListener listener) {
		this.externalListeners.add(listener);
	}

	public void removeLocalListener(SystemListener listener) {
		this.localListeners.remove(listener);
	}
	
	public void removeExternalListener(SystemListener listener) {
		this.externalListeners.remove(listener);
	}

	
	public void dispatchDefineNameEvent(SystemEvent event, DispatchType type) {
		List<SystemListener> copyList;
		Iterator<SystemListener> listener;
		
		switch (type) {
			case EXTERNAL:
				copyList = new ArrayList<SystemListener>(this.externalListeners);
				Collections.copy(copyList, this.externalListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).defineName(event);
				}
				break;
			case LOCAL:
				copyList = new ArrayList<SystemListener>(this.localListeners);
				Collections.copy(copyList, this.localListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).defineName(event);
				}
				break;
		}
	}
	
	public void dispatchNameAcceptedEvent(SystemEvent event, DispatchType type) {
		List<SystemListener> copyList;
		Iterator<SystemListener> listener;
		
		switch (type) {
			case EXTERNAL:
				copyList = new ArrayList<SystemListener>(this.externalListeners);
				Collections.copy(copyList, this.externalListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).nameAccepted(event);
				}
				break;
			case LOCAL:
				copyList = new ArrayList<SystemListener>(this.localListeners);
				Collections.copy(copyList, this.localListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).nameAccepted(event);
				}
				break;
		}
	}
	
	public void dispatchNameDeclinedEvent(SystemEvent event, DispatchType type) {
		List<SystemListener> copyList;
		Iterator<SystemListener> listener;
		
		switch (type) {
			case EXTERNAL:
				copyList = new ArrayList<SystemListener>(this.externalListeners);
				Collections.copy(copyList, this.externalListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).nameDeclined(event);
				}
				break;
			case LOCAL:
				copyList = new ArrayList<SystemListener>(this.localListeners);
				Collections.copy(copyList, this.localListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).nameDeclined(event);
				}
				break;
		}
	}
	
	public void dispatchSetPlayerList(PlayerListEvent event, DispatchType type) {
		List<SystemListener> copyList;
		Iterator<SystemListener> listener;
		
		switch (type) {
			case EXTERNAL:
				copyList = new ArrayList<SystemListener>(this.externalListeners);
				Collections.copy(copyList, this.externalListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).setPlayerList(event);
				}
				break;
			case LOCAL:
				copyList = new ArrayList<SystemListener>(this.localListeners);
				Collections.copy(copyList, this.localListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).setPlayerList(event);
				}
				break;
		}
	}
	
	public void dispatchGetPlayerList(DispatchType type) {
		List<SystemListener> copyList;
		Iterator<SystemListener> listener;
		
		switch (type) {
			case EXTERNAL:
				copyList = new ArrayList<SystemListener>(this.externalListeners);
				Collections.copy(copyList, this.externalListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).getPlayerList();
				}
				break;
			case LOCAL:
				copyList = new ArrayList<SystemListener>(this.localListeners);
				Collections.copy(copyList, this.localListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).getPlayerList();
				}
				break;
		}
	}
	
	public void dispatchPlayerJoined(PlayerListEvent event, DispatchType type) {
		List<SystemListener> copyList;
		Iterator<SystemListener> listener;
		
		switch (type) {
			case EXTERNAL:
				copyList = new ArrayList<SystemListener>(this.externalListeners);
				Collections.copy(copyList, this.externalListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).playerJoined(event);
				}
				break;
			case LOCAL:
				copyList = new ArrayList<SystemListener>(this.localListeners);
				Collections.copy(copyList, this.localListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).playerJoined(event);
				}
				break;
		}
	}
	
	public void dispatchPlayerLeft(PlayerListEvent event, DispatchType type) {
		List<SystemListener> copyList;
		Iterator<SystemListener> listener;
		
		switch (type) {
			case EXTERNAL:
				copyList = new ArrayList<SystemListener>(this.externalListeners);
				Collections.copy(copyList, this.externalListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).playerLeft(event);
				}
				break;
			case LOCAL:
				copyList = new ArrayList<SystemListener>(this.localListeners);
				Collections.copy(copyList, this.localListeners);
				listener = copyList.iterator();
				while( listener.hasNext() ) {
					((SystemListener) listener.next()).playerLeft(event);
				}
				break;
		}
	}
	
}
